package com.thread.threadfirst.studyThread3;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * 8、DelayQueue（延迟Queue）无界Queue
 * 在此容器中的每个元素可看做一个任务，而这个任务什么时候可以被消费者消费呢，每个任务都记录着还有多长时间可以被消费者消费，
 * 排在此队列最前面的是等待时间最短的，也是最先被消费者消费的。
 * <p>
 * 此DelayQueue可用来执行定时任务。
 */
public class T6 {
    static BlockingQueue tasks = new DelayQueue();

    static class MyTask implements Delayed {  //DelayQueue在执行put()方法时的参数是一个继承了Delayed的对象，所以此处写了一个静态内部类 实现了Delayed接口 所以需要实现它的getDelay()方法，
        // 由于Delayed接口继承了Comparable，所以需要实现compareTo()方法。
        long runtime;

        public MyTask(long runtime) {
            this.runtime = runtime;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(runtime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed o) {
            if (this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS))
                return -1;
            else if (this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS))
                return 1;
            else
                return 0;
        }

        @Override
        public String toString() {  //注意：代码中如果没有重写（override）toString()方法的话，那么执行System.out.println(tasks);输出的是一些对象的内存地址，故需要override toString()方法
            return "" + runtime;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        long now = System.currentTimeMillis();
        MyTask task1 = new MyTask(now + 1000);
        MyTask task2 = new MyTask(now + 2000);
        MyTask task3 = new MyTask(now + 1500);
        MyTask task4 = new MyTask(now + 2500);
        MyTask task5 = new MyTask(now + 500);

        tasks.put(task1);
        tasks.put(task2);
        tasks.put(task3);
        tasks.put(task4);
        tasks.put(task5);

        System.out.println(tasks);

        for (int i = 0; i < 5; i++) {
            System.out.println(tasks.take());  //从结果可看出时间先结束的先被消费者消费。注意：此方法不会阻塞
        }
    }

}
